<!DOCTYPE html>
<html lang=zh>
<head>
  <meta charset="utf-8">
  
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
  <meta name="renderer" content="webkit">
  <meta http-equiv="Cache-Control" content="no-transform" />
  <meta http-equiv="Cache-Control" content="no-siteapp" />
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="format-detection" content="telephone=no,email=no,adress=no">
  <!-- Color theme for statusbar -->
  <meta name="theme-color" content="#000000" />
  <!-- 强制页面在当前窗口以独立页面显示,防止别人在框架里调用页面 -->
  <meta http-equiv="window-target" content="_top" />
  
  
  <title>Spring 注解开发 | Hexo</title>
  <meta name="description" content="Spring 注解开发1.@Bean注解和@Configration注解在原来的Spring开发中，我们都是通过配置xml的方式，通过bean标签将对象放到IOC容器中，例如 1234&lt;bean id &#x3D; &quot;person&quot; class &#x3D; &quot;cn.jack.Person&quot;&gt;	&lt;property name &#x3D; &quot;name&quot;">
<meta property="og:type" content="article">
<meta property="og:title" content="Spring 注解开发">
<meta property="og:url" content="https://tongxuema.gitee.io/2019/08/12/Spring%20%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%8F%91/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="Spring 注解开发1.@Bean注解和@Configration注解在原来的Spring开发中，我们都是通过配置xml的方式，通过bean标签将对象放到IOC容器中，例如 1234&lt;bean id &#x3D; &quot;person&quot; class &#x3D; &quot;cn.jack.Person&quot;&gt;	&lt;property name &#x3D; &quot;name&quot;">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="c:/Users/MGL/Desktop/学习笔记/Spring中所有BeanPostProcessor的实现类.jpg">
<meta property="og:image" content="c:/Users/MGL/Desktop/Snipaste_2019-06-16_13-51-13.jpg">
<meta property="article:published_time" content="2019-08-12T04:56:10.000Z">
<meta property="article:modified_time" content="2021-03-02T13:41:31.572Z">
<meta property="article:author" content="John Doe">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="c:/Users/MGL/Desktop/学习笔记/Spring中所有BeanPostProcessor的实现类.jpg">
  <!-- Canonical links -->
  <link rel="canonical" href="https://tongxuema.gitee.io/2019/08/12/Spring%20%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%8F%91/index.html">
  
    <link rel="alternate" href="/atom.xml" title="Hexo" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png" type="image/x-icon">
  
  
<link rel="stylesheet" href="/css/style.css">

  
  
  
  
<meta name="generator" content="Hexo 5.4.0"></head>


<body class="main-center" itemscope itemtype="http://schema.org/WebPage">
  <header class="header" itemscope itemtype="http://schema.org/WPHeader">
  <div class="slimContent">
    <div class="navbar-header">
      
      
      <div class="profile-block text-center">
        <a id="avatar" href="https://github.com/ysuMgl" target="_blank">
          <img class="img-circle img-rotate" src="https://ftp.bmp.ovh/imgs/2021/03/6eb8924aba7eb620.gif" width="200" height="200">
        </a>
        <h2 id="name" class="hidden-xs hidden-sm">清平愿</h2>
        <h3 id="title" class="hidden-xs hidden-sm hidden-md"></h3>
        <small id="location" class="text-muted hidden-xs hidden-sm"><i class="icon icon-map-marker"></i> Hebei, China</small>
      </div>
      
      <div class="search" id="search-form-wrap">

    <form class="search-form sidebar-form">
        <div class="input-group">
            <input type="text" class="search-form-input form-control" placeholder="搜索" />
            <span class="input-group-btn">
                <button type="submit" class="search-form-submit btn btn-flat" onclick="return false;"><i class="icon icon-search"></i></button>
            </span>
        </div>
    </form>
    <div class="ins-search">
  <div class="ins-search-mask"></div>
  <div class="ins-search-container">
    <div class="ins-input-wrapper">
      <input type="text" class="ins-search-input" placeholder="想要查找什么..." x-webkit-speech />
      <button type="button" class="close ins-close ins-selectable" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
    </div>
    <div class="ins-section-wrapper">
      <div class="ins-section-container"></div>
    </div>
  </div>
</div>


</div>
      <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#main-navbar" aria-controls="main-navbar" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
    </div>
    <nav id="main-navbar" class="collapse navbar-collapse" itemscope itemtype="http://schema.org/SiteNavigationElement" role="navigation">
      <ul class="nav navbar-nav main-nav ">
        
        
        <li class="menu-item menu-item-home">
          <a href="/.">
            
            <i class="icon icon-home-fill"></i>
            
            <span class="menu-title">首页</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-archives">
          <a href="/archives">
            
            <i class="icon icon-archives-fill"></i>
            
            <span class="menu-title">归档</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-categories">
          <a href="/categories">
            
            <i class="icon icon-folder"></i>
            
            <span class="menu-title">分类</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-tags">
          <a href="/tags">
            
            <i class="icon icon-tags"></i>
            
            <span class="menu-title">标签</span>
          </a>
        </li>
        
      </ul>
      
	
    <ul class="social-links">
    	
        <li><a href="https://github.com/ysuMgl" target="_blank" title="Github" data-toggle=tooltip data-placement=top><i class="icon icon-github"></i></a></li>
        
        <li><a href="http://weibo.com/cofess" target="_blank" title="Weibo" data-toggle=tooltip data-placement=top><i class="icon icon-weibo"></i></a></li>
        
        <li><a href="https://gitee.com/tongxuema" target="_blank" title="Gitee" data-toggle=tooltip data-placement=top><i class="icon icon-gitee"></i></a></li>
        
    </ul>

    </nav>
  </div>
</header>

  
    <aside class="sidebar" itemscope itemtype="http://schema.org/WPSideBar">
  <div class="slimContent">
    
      <div class="widget">
    <h3 class="widget-title">公告</h3>
    <div class="widget-body">
        <div id="board">
            <div class="content">
                <p>欢迎交流与分享经验!</p>
            </div>
        </div>
    </div>
</div>

    
      
  <div class="widget">
    <h3 class="widget-title">分类</h3>
    <div class="widget-body">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/Java%E5%BC%80%E5%8F%91/">Java开发</a><span class="category-list-count">1</span></li></ul>
    </div>
  </div>


    
      

    
      
    
      
  <div class="widget">
    <h3 class="widget-title">归档</h3>
    <div class="widget-body">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/02/">二月 2021</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/08/">八月 2019</a><span class="archive-list-count">1</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget">
    <h3 class="widget-title">最新文章</h3>
    <div class="widget-body">
      <ul class="recent-post-list list-unstyled no-thumbnail">
        
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                
              </p>
              <p class="item-title">
                <a href="/2021/02/28/hello-world/" class="title">Hello World</a>
              </p>
              <p class="item-date">
                <time datetime="2021-02-28T03:07:35.542Z" itemprop="datePublished">2021-02-28</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/categories/Java%E5%BC%80%E5%8F%91/">Java开发</a>
              </p>
              <p class="item-title">
                <a href="/2019/08/12/Spring%20%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%8F%91/" class="title">Spring 注解开发</a>
              </p>
              <p class="item-date">
                <time datetime="2019-08-12T04:56:10.000Z" itemprop="datePublished">2019-08-12</time>
              </p>
            </div>
          </li>
          
      </ul>
    </div>
  </div>
  

    
  </div>
</aside>

  
  
<aside class="sidebar sidebar-toc collapse" id="collapseToc" itemscope itemtype="http://schema.org/WPSideBar">
  <div class="slimContent">
    <nav id="toc" class="article-toc">
      <h3 class="toc-title">文章目录</h3>
      <ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#Spring-%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%8F%91"><span class="toc-number">1.</span> <span class="toc-text">Spring 注解开发</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-Bean%E6%B3%A8%E8%A7%A3%E5%92%8C-Configration%E6%B3%A8%E8%A7%A3"><span class="toc-number">1.1.</span> <span class="toc-text">1.@Bean注解和@Configration注解</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-ComponentScan%E6%B3%A8%E8%A7%A3"><span class="toc-number">1.2.</span> <span class="toc-text">2.@ComponentScan注解</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-FilterType%E8%AE%BE%E7%BD%AE%E6%8C%87%E5%AE%9A%E8%BF%87%E6%BB%A4%E8%A7%84%E5%88%99"><span class="toc-number">1.3.</span> <span class="toc-text">3.FilterType设置指定过滤规则</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E2%91%A0%E9%80%9A%E8%BF%87excludeFilters%E6%8E%92%E9%99%A4%E6%8C%87%E5%AE%9A%E6%B3%A8%E8%A7%A3%E5%8C%85%E5%90%AB%E7%9A%84%E7%B1%BB"><span class="toc-number">1.3.1.</span> <span class="toc-text">①通过excludeFilters排除指定注解包含的类</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E2%91%A1%E9%80%9A%E8%BF%87includeFilters%E5%8F%AA%E5%8C%85%E5%90%AB%E7%89%B9%E5%AE%9A%E6%B3%A8%E8%A7%A3%E6%A0%87%E6%B3%A8%E7%9A%84%E7%B1%BB"><span class="toc-number">1.3.2.</span> <span class="toc-text">②通过includeFilters只包含特定注解标注的类</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E2%91%A2%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A7%84%E5%88%99%E5%8C%B9%E9%85%8D"><span class="toc-number">1.3.3.</span> <span class="toc-text">③自定义规则匹配</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-Scope%E6%B3%A8%E8%A7%A3"><span class="toc-number">1.4.</span> <span class="toc-text">4.@Scope注解</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5-Lazy%E6%87%92%E5%8A%A0%E8%BD%BD%E6%B3%A8%E8%A7%A3"><span class="toc-number">1.5.</span> <span class="toc-text">5.@Lazy懒加载注解</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6-Conditional%E6%B3%A8%E8%A7%A3"><span class="toc-number">1.6.</span> <span class="toc-text">6.@Conditional注解</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7-Import%E6%B3%A8%E8%A7%A3"><span class="toc-number">1.7.</span> <span class="toc-text">7.Import注解</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#8-%E9%80%9A%E8%BF%87FactoryBean%E5%B7%A5%E5%8E%82%E5%88%9B%E5%BB%BA%E5%AE%9E%E4%BE%8B%EF%BC%8C%E6%94%BE%E5%88%B0IOC%E5%AE%B9%E5%99%A8"><span class="toc-number">1.8.</span> <span class="toc-text">8.通过FactoryBean工厂创建实例，放到IOC容器</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#9-%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96%E6%96%B9%E6%B3%95%E5%92%8C%E9%94%80%E6%AF%81%E6%96%B9%E6%B3%95"><span class="toc-number">1.9.</span> <span class="toc-text">9.对象的初始化方法和销毁方法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#10-%E7%90%86%E8%A7%A3BeanPostProcessor%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%EF%BC%88%E7%9C%8B%E6%BA%90%E7%A0%81%EF%BC%8C%E6%9C%89%E7%82%B9%E9%9A%BE%EF%BC%89"><span class="toc-number">1.10.</span> <span class="toc-text">10.理解BeanPostProcessor实现原理（看源码，有点难）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#11-BeanPostProcessor%E6%8E%A5%E5%8F%A3%E5%9C%A8Spring%E5%85%B6%E4%BB%96%E7%B1%BB%E4%B8%AD%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="toc-number">1.11.</span> <span class="toc-text">11.BeanPostProcessor接口在Spring其他类中的使用</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#12-Value%E6%B3%A8%E8%A7%A3%E5%92%8C-PropertySource%E6%B3%A8%E8%A7%A3%E7%BB%99%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%B1%9E%E6%80%A7%E8%B5%8B%E5%80%BC"><span class="toc-number">1.12.</span> <span class="toc-text">12.@Value注解和@PropertySource注解给对象的属性赋值</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#13-%E4%BD%BF%E7%94%A8-Autowired%E6%B3%A8%E8%A7%A3%E8%87%AA%E5%8A%A8%E6%B3%A8%E5%85%A5%E7%9A%84%E8%AE%B2%E8%A7%A3"><span class="toc-number">1.13.</span> <span class="toc-text">13.使用@Autowired注解自动注入的讲解</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#14-%E4%BD%BF%E7%94%A8-Resource%E5%92%8C-Inject%E6%B3%A8%E8%A7%A3%E5%AE%9E%E7%8E%B0%E8%87%AA%E5%8A%A8%E6%B3%A8%E5%85%A5"><span class="toc-number">1.14.</span> <span class="toc-text">14.使用@Resource和@Inject注解实现自动注入</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#15-%E9%80%9A%E8%BF%87Aware%E6%8E%A5%E5%8F%A3%E7%BB%99%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84%E7%BB%84%E4%BB%B6%E6%B7%BB%E5%8A%A0Spring%E5%BA%95%E5%B1%82%E7%9A%84%E7%BB%84%E4%BB%B6%EF%BC%88%E4%BE%8B%E5%A6%82ApplicationContext%EF%BC%8CBeanfactory%E7%AD%89%EF%BC%89"><span class="toc-number">1.15.</span> <span class="toc-text">15.通过Aware接口给自定义的组件添加Spring底层的组件（例如ApplicationContext，Beanfactory等）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#16-%E4%BD%BF%E7%94%A8-Profile%E6%B3%A8%E8%A7%A3%E5%AE%9E%E7%8E%B0%E4%B8%8D%E5%90%8C%E7%8E%AF%E5%A2%83%E7%9A%84%E5%88%87%E6%8D%A2"><span class="toc-number">1.16.</span> <span class="toc-text">16.使用@Profile注解实现不同环境的切换</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#17-%E4%BD%BF%E7%94%A8AOP%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%8F%91%EF%BC%8C%E9%80%9A%E8%BF%87%E6%B3%A8%E8%A7%A3-EnableAspectJAutoProxy%E6%B3%A8%E8%A7%A3"><span class="toc-number">1.17.</span> <span class="toc-text">17.使用AOP注解开发，通过注解@EnableAspectJAutoProxy注解</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#18-EnableAspectJAutoProxy%E6%B3%A8%E8%A7%A3%E8%AF%A6%E8%A7%A3"><span class="toc-number">1.18.</span> <span class="toc-text">18.@EnableAspectJAutoProxy注解详解</span></a></li></ol></li></ol>
    </nav>
  </div>
</aside>


<main class="main" role="main">
  <div class="content">
  <article id="post-Spring 注解开发" class="article article-type-post" itemscope itemtype="http://schema.org/BlogPosting">
    
    <div class="article-header">
      
        
  
    <h1 class="article-title" itemprop="name">
      Spring 注解开发
    </h1>
  

      
      <div class="article-meta">
        <span class="article-date">
    <i class="icon icon-calendar-check"></i>
	<a href="/2019/08/12/Spring%20%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%8F%91/" class="article-date">
	  <time datetime="2019-08-12T04:56:10.000Z" itemprop="datePublished">2019-08-12</time>
	</a>
</span>
        
  <span class="article-category">
    <i class="icon icon-folder"></i>
    <a class="article-category-link" href="/categories/Java%E5%BC%80%E5%8F%91/">Java开发</a>
  </span>

        

        

	<span class="article-read hidden-xs">
    	<i class="icon icon-eye-fill" aria-hidden="true"></i>
    	<span id="/2019/08/12/Spring%20%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%8F%91/" class="leancloud_visitors"  data-flag-title="Spring 注解开发">
			<span class="leancloud-visitors-count">0</span>
		</span>
    </span>

        <span class="post-comment"><i class="icon icon-comment"></i> <a href="/2019/08/12/Spring%20%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%8F%91/#comments" class="article-comment-link">评论</a></span>
        
      </div>
    </div>
    <div class="article-entry marked-body" itemprop="articleBody">
      
        <h3 id="Spring-注解开发"><a href="#Spring-注解开发" class="headerlink" title="Spring 注解开发"></a>Spring 注解开发</h3><h4 id="1-Bean注解和-Configration注解"><a href="#1-Bean注解和-Configration注解" class="headerlink" title="1.@Bean注解和@Configration注解"></a>1.@Bean注解和@Configration注解</h4><p>在原来的Spring开发中，我们都是通过配置xml的方式，通过bean标签将对象放到IOC容器中，例如</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span> = <span class="string">&quot;person&quot;</span> <span class="attr">class</span> = <span class="string">&quot;cn.jack.Person&quot;</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">&quot;name&quot;</span> <span class="attr">value</span> = <span class="string">&quot;zhangsan&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span> = <span class="string">&quot;age&quot;</span> <span class="attr">value</span> = <span class="string">&quot;20&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>然后在测试类中获取IOC容器中对象的方法为：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test1</span><span class="params">()</span></span>&#123;</span><br><span class="line">       ClassPathXmlApplicationContext applicationContext = <span class="keyword">new</span> ClassPathXmlApplicationContext(<span class="string">&quot;beans.xml&quot;</span>);</span><br><span class="line">       Person person = (Person) applicationContext.getBean(<span class="string">&quot;person&quot;</span>);</span><br><span class="line">       System.out.println(person);</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<p>如果通过Spring注解的方式，则不需要这些配置文件，需要建立一个配置类来顶替配置文件，在<strong>配置类上面标注@Configration注解</strong>，表明这个类是一个配置类。通过在类中定义相应返回值的方法，标注@Bean注解。<strong>Spring默认将方法名称作为id，方法返回值类型作为class</strong>，如果要自定义id的话，在@Bean注解value值设为相应的id。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainConfig</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Person <span class="title">person</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Person(<span class="string">&quot;lisi&quot;</span>,<span class="number">20</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean(&quot;person1&quot;)</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Person <span class="title">other</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Person(<span class="string">&quot;zhagnsan&quot;</span>,<span class="number">18</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>通过定义配置类，将相应对象放到了IOC容器中，那么我们如何像xml方式那种获取对应的ApplicationContext呢？</p>
<p>也是类似，我们需要通过一个new 一个AnnotationConfigApplicationContext类的对象，这个对象也实现了ApplicationContext接口，需要传进去一个参数，就是这配置类的class对象。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ApplicationContext applicationContext = <span class="keyword">new</span> AnnotationConfigApplicationContext(MainConfig.class);</span><br></pre></td></tr></table></figure>

<p>获取到ApplicationContext对象后，和xml方式的操作就保持一致了。可以获取IOC容器中的对象，getBean方法，获取对象名称等。</p>
<h4 id="2-ComponentScan注解"><a href="#2-ComponentScan注解" class="headerlink" title="2.@ComponentScan注解"></a>2.@ComponentScan注解</h4><p>@ComponentScan是组件包扫描注解，在 原来的xml开发中，在context:component-scan标签中添加相应的包名，将标有@Controller，@Service，@Repository，@Component注解的类放到IOC容器中</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;cn.jack&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<p>在配置类上，与配置文件类似，我们需要在配置类上面添加@ComponentScan注解，查看@ComponentScan注解的代码，里面value对应的就是和配置文件类似的base-package，还有两个重要的</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Filter[] includeFilters() <span class="keyword">default</span> &#123;&#125;;</span><br><span class="line"></span><br><span class="line">Filter[] excludeFilters() <span class="keyword">default</span> &#123;&#125;;</span><br></pre></td></tr></table></figure>

<p>其中<strong>includeFilters</strong>是只包含哪些，<strong>excludeFilters</strong>是不包含哪些，它们都是Filter数组型的。</p>
<p>关于这个Filter，英文来说这个是过滤器，通过查看源代码发现，Filter也是一个注解，注解代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class="line">	<span class="meta">@Target(&#123;&#125;)</span></span><br><span class="line">	<span class="meta">@interface</span> Filter &#123;</span><br><span class="line">        </span><br><span class="line">		<span class="function">FilterType <span class="title">type</span><span class="params">()</span> <span class="keyword">default</span> FilterType.ANNOTATION</span>;</span><br><span class="line">        </span><br><span class="line">		<span class="meta">@AliasFor(&quot;classes&quot;)</span></span><br><span class="line">		Class&lt;?&gt;[] value() <span class="keyword">default</span> &#123;&#125;;</span><br><span class="line"></span><br><span class="line">		<span class="meta">@AliasFor(&quot;value&quot;)</span></span><br><span class="line">		Class&lt;?&gt;[] classes() <span class="keyword">default</span> &#123;&#125;;</span><br><span class="line"></span><br><span class="line">		String[] pattern() <span class="keyword">default</span> &#123;&#125;;</span><br><span class="line">	&#125;</span><br></pre></td></tr></table></figure>

<p>我们需要定义过滤的方法，即FilterType，默认值为ANNOTATION注解，还有ASSIGNABLE_TYPE：类，aspectj，正则等。</p>
<p>所以如果我们要想排除标注某些注解的类如@Controller和@Service注解，那么，我们应该怎么做呢？</p>
<h4 id="3-FilterType设置指定过滤规则"><a href="#3-FilterType设置指定过滤规则" class="headerlink" title="3.FilterType设置指定过滤规则"></a>3.FilterType设置指定过滤规则</h4><h5 id="①通过excludeFilters排除指定注解包含的类"><a href="#①通过excludeFilters排除指定注解包含的类" class="headerlink" title="①通过excludeFilters排除指定注解包含的类"></a>①通过excludeFilters排除指定注解包含的类</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ComponentScan(value = &quot;cn.jack&quot; ,excludeFilters = &#123;</span></span><br><span class="line"><span class="meta">        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = &#123;</span></span><br><span class="line"><span class="meta">                Controller.class, Service.class</span></span><br><span class="line"><span class="meta">        &#125;)</span></span><br><span class="line"><span class="meta">&#125;)</span></span><br></pre></td></tr></table></figure>

<h5 id="②通过includeFilters只包含特定注解标注的类"><a href="#②通过includeFilters只包含特定注解标注的类" class="headerlink" title="②通过includeFilters只包含特定注解标注的类"></a>②通过includeFilters只包含特定注解标注的类</h5><p>如果要只包换@Controller和@Service注解的类呢，主要要添加一个useDefaultFilters = false,禁用默认的过滤器（全包含）。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ComponentScan(value = &quot;cn.jack&quot; ,includeFilters = &#123;</span></span><br><span class="line"><span class="meta">        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = &#123;</span></span><br><span class="line"><span class="meta">                Controller.class,Service.class</span></span><br><span class="line"><span class="meta">        &#125;)</span></span><br><span class="line"><span class="meta">&#125;,useDefaultFilters = false)</span></span><br></pre></td></tr></table></figure>

<h5 id="③自定义规则匹配"><a href="#③自定义规则匹配" class="headerlink" title="③自定义规则匹配"></a>③自定义规则匹配</h5><p>如果想自定义匹配规则的话，需要在Filter的type中设置type = FilterType.CUSTOM，classes中写实现TypeFilter接口的class对象。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ComponentScan(value = &quot;cn.jack&quot; ,includeFilters = &#123;</span></span><br><span class="line"><span class="meta">        @ComponentScan.Filter(type = FilterType.CUSTOM,classes = &#123;</span></span><br><span class="line"><span class="meta">                MyTypeFilter.class</span></span><br><span class="line"><span class="meta">        &#125;)</span></span><br><span class="line"><span class="meta">&#125;,useDefaultFilters = false)</span></span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyTypeFilter</span> <span class="keyword">implements</span> <span class="title">TypeFilter</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> metadataReader</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> metadataReaderFactory</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IOException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">match</span><span class="params">(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//获取当前注解类的信息</span></span><br><span class="line">        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();</span><br><span class="line">        <span class="comment">//获取当前正在扫描的类的类信息</span></span><br><span class="line">        ClassMetadata classMetadata = metadataReader.getClassMetadata();</span><br><span class="line">        <span class="comment">//获取当前类资源（类的路径）</span></span><br><span class="line">        Resource resource = metadataReader.getResource();</span><br><span class="line"></span><br><span class="line">        String className = classMetadata.getClassName();</span><br><span class="line">        System.out.println(<span class="string">&quot;---&gt;&quot;</span> + className);</span><br><span class="line">        <span class="keyword">if</span>(className.contains(<span class="string">&quot;er&quot;</span>))&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="4-Scope注解"><a href="#4-Scope注解" class="headerlink" title="4.@Scope注解"></a>4.@Scope注解</h4><p>顾名思义哈，scope是作用域的意思，在spring中可以有四种作用域，一个是单实例，一个是多实例，request域，session域。</p>
<p>在xml中，也有相似的配置。在每个bean标签中有一个scope属性，属性的值也是这四个。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">  <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@see</span> ConfigurableBeanFactory#SCOPE_PROTOTYPE</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@see</span> ConfigurableBeanFactory#SCOPE_SINGLETON</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@see</span> org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@see</span> org.springframework.web.context.WebApplicationContext#SCOPE_SESSION</span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line"></span><br><span class="line">String SCOPE_SINGLETON = <span class="string">&quot;singleton&quot;</span>;</span><br><span class="line">String SCOPE_PROTOTYPE = <span class="string">&quot;prototype&quot;</span>;</span><br><span class="line"></span><br><span class="line">String SCOPE_REQUEST = <span class="string">&quot;request&quot;</span>;</span><br><span class="line">String SCOPE_SESSION = <span class="string">&quot;session&quot;</span>;</span><br></pre></td></tr></table></figure>

<p>SCOPE_SINGLETON：单实例，Spring默认。对象在IOC容器创建之后就会放入进去。</p>
<p>SCOPE_PROTOTYPE：多实例，对象在IOC容器创建之后不会立马放进去，在通过getBean方法取相应的对象的之前放进去，每次通过getBean取一次，就会放入一次。</p>
<p>SCOPE_REQUEST：每一次的request请求，创建一个相应的对象（不用，一般我们通过直接setAttribute方法将相应对象放入容器中）</p>
<p>SCOPE_SESSION：每次回话，创建一个相应的对象（也不用，同上）</p>
<h4 id="5-Lazy懒加载注解"><a href="#5-Lazy懒加载注解" class="headerlink" title="5.@Lazy懒加载注解"></a>5.@Lazy懒加载注解</h4><p>@Lazy注解只针对于<strong>单实例</strong>。这个比较好理解，因为单实例状态下，在容器初始化完成后就会向IOC容器中添加组件。但是标注@Lazy注解后，添加组件是在第一次使用时添加，并且也只会添加一次。</p>
<h4 id="6-Conditional注解"><a href="#6-Conditional注解" class="headerlink" title="6.@Conditional注解"></a>6.@Conditional注解</h4><p>规定需要添加一些条件，只有满足条件才能将对象注册到IOC容器中。@Conditional注解中的value值为Condition接口的实现类，所以要自定义一个类来实现Condition接口，定义匹配规则。</p>
<p>这个注解可以定义在类上面，还可以定义在方法上面。</p>
<ul>
<li>定义在类上面，表示当匹配满足匹配规则时，将类上的所有bean都放到IOC容器中。</li>
<li>定义在方法上面，表示当满足匹配规则时，将标注@Bean注解对应的方法的返回值放到IOC容器中。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> Conditional &#123;</span><br><span class="line">    <span class="comment">//value值为Condition接口的实现类</span></span><br><span class="line">	Class&lt;? extends Condition&gt;[] value();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Condition</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">boolean</span> <span class="title">matches</span><span class="params">(ConditionContext context, AnnotatedTypeMetadata metadata)</span></span>;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>其中</p>
<ul>
<li>ConditionContext：这个类的对象表示判断条件的上下文（条件）</li>
<li>AnnotatedTypeMetadata：这个类的对象表示注释信息</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">ConditionContext</span> </span>&#123;</span><br><span class="line">	<span class="comment">//获取到bean定义的注册类，用于注册bean的类</span></span><br><span class="line">	<span class="function">BeanDefinitionRegistry <span class="title">getRegistry</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="comment">//获取到bean的创建工厂，IOC的beanFactory</span></span><br><span class="line">	<span class="function">ConfigurableListableBeanFactory <span class="title">getBeanFactory</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="comment">//得到当前环境信息</span></span><br><span class="line">	<span class="function">Environment <span class="title">getEnvironment</span><span class="params">()</span></span>;</span><br><span class="line">	<span class="function">ResourceLoader <span class="title">getResourceLoader</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="comment">//得到类加载器</span></span><br><span class="line">	<span class="function">ClassLoader <span class="title">getClassLoader</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="7-Import注解"><a href="#7-Import注解" class="headerlink" title="7.Import注解"></a>7.Import注解</h4><p>和**@Bean**注解实现的功能类似，都是向容器中添加组件，不同的是，@Import注解是添加在配置类上面，注解内部的参数是class类型的数组，文档中写到，可以导入的有标注@Configration注解、ImportSelector实现类、ImportBeanDefinitionRegistrar实现类和一些常规的类。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> Import &#123;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/**</span></span><br><span class="line"><span class="comment">	 * &#123;<span class="doctag">@link</span> Configuration&#125;, &#123;<span class="doctag">@link</span> ImportSelector&#125;, &#123;<span class="doctag">@link</span> ImportBeanDefinitionRegistrar&#125;</span></span><br><span class="line"><span class="comment">	 * or regular component classes to import.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	Class&lt;?&gt;[] value();</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>@Configuration：标注这个注解的类成为配置类，替代配置文件用的。把这个class导入进来后，这个配置类中添加到IOC容器的对象，同样也会添加到新的配置类对应的IOC容器中。</li>
<li>ImportSelector：这个是接口，实现类需要重写返回值为String[] 的方法selectImports，即将需要导入的类的全路径写在这数组中。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">ImportSelector</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/**</span></span><br><span class="line"><span class="comment">	 * Select and return the names of which class(es) should be imported based on</span></span><br><span class="line"><span class="comment">	 * the &#123;<span class="doctag">@link</span> AnnotationMetadata&#125; of the importing @&#123;<span class="doctag">@link</span> Configuration&#125; class.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	String[] selectImports(AnnotationMetadata importingClassMetadata);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>ImportBeanDefinitionRegistrar：这也是一个接口，实现类需要重写方法如下</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">ImportBeanDefinitionRegistrar</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">registerBeanDefinitions</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)</span></span>;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li><ul>
<li>AnnotationMetadata：注解信息</li>
<li>BeanDefinitionRegistry：bean的定义注册类，可以通过这个对象自定义向IOC容器中注入组件。</li>
</ul>
</li>
</ul>
<h4 id="8-通过FactoryBean工厂创建实例，放到IOC容器"><a href="#8-通过FactoryBean工厂创建实例，放到IOC容器" class="headerlink" title="8.通过FactoryBean工厂创建实例，放到IOC容器"></a>8.通过FactoryBean工厂创建实例，放到IOC容器</h4><p>FactoryBean是接口，在IOC容器中添加这个接口的实现类后，通过getBean返回得到的对象是这个工厂的getObject方法的返回值。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">FactoryBean</span>&lt;<span class="title">T</span>&gt; </span>&#123;</span><br><span class="line"></span><br><span class="line">	<span class="function">T <span class="title">getObject</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>;</span><br><span class="line"></span><br><span class="line">	Class&lt;?&gt; getObjectType();</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">boolean</span> <span class="title">isSingleton</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>可以自定义一个工厂，比如ColorFactoryBean，这个工厂就是实例化Color对象的工厂，放到IOC容器中，getBean得到的就是color对象，比如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ColorFactoryBean</span> <span class="keyword">implements</span> <span class="title">FactoryBean</span>&lt;<span class="title">Color</span>&gt; </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Color <span class="title">getObject</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Color();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Class&lt;?&gt; getObjectType() &#123;</span><br><span class="line">        <span class="keyword">return</span> Color.class;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isSingleton</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在配置类中添加一个bean为ColorFactoryBean，通过getBean后得到的就是color。</p>
<p><strong>但是如果你想得到这个工厂对象的话，需要在getBean中id加一个“&amp;”号，Spring在BeanFactory接口中定义了前缀为这个符号。</strong></p>
<h4 id="9-对象的初始化方法和销毁方法"><a href="#9-对象的初始化方法和销毁方法" class="headerlink" title="9.对象的初始化方法和销毁方法"></a>9.对象的初始化方法和销毁方法</h4><ul>
<li>自定义初始化方法和销毁方法<ul>
<li>类似于配置文件，在bean标签中配置init-method属性和destroy-method属性，来指定对象的初始化和销毁方法，方法中不能有任何的参数，但可以抛出任何异常。</li>
<li>在配置类中的写法是，在bean注解中，写出对应的initMethod方法和destroyMethod方法。</li>
<li>对于单实例来说，在容器初始化的时候就会把对应的对象放到IOC容器中，也会调用它的initMethod，在容器关闭时，会调用对象的destroyMethod。</li>
<li>对于多实例来说，在容器初始化的时候不会将对象放到IOC容器中，只有在你要调用这个对象的时候，IOC容器才会给你实例对象，并放到IOC容器中。而且，在容器关闭的时候，对象也不会销毁。这表明，IOC容器只是帮你实例化对象，对于对象的销毁工作，将由你自己来完成。</li>
</ul>
</li>
<li>使用Spring为我们提供的两个接口来实现对象的初始化和销毁方法<ul>
<li>InitializingBean接口：内有方法afterPropertiesSet，即属性设置完成后的方法，也就是初始化方法。</li>
<li>DisposableBean接口：内有方法destroy，对象的销毁方法。</li>
</ul>
</li>
<li>基于jsr250注解来实现<ul>
<li>@PostConstruct注解：对象实例化，并做好初始化工作的时候被调用。</li>
<li>@PreDestroy注解：在销毁对象前进行回调。</li>
</ul>
</li>
<li>实现BeanPostProcessor接口（后置处理器），接口定义了两个方法，postProcessBeforeInitialization和postProcessAfterInitialization。<ul>
<li>postProcessBeforeInitialization：在你给定的bean的初始化方法调用之前调用，这些初始化方法包括自定义的init-method方法或者实现Spring的InitializingBean接口的afterPropertiesSet方法调用之前调用。</li>
<li>postProcessAfterInitialization：在你给定的bean的初始化方法调用之后调用，这些初始化方法包括自定义的init-method方法或者实现Spring的DisposableBean接口的destroy方法调用之后调用。</li>
</ul>
</li>
</ul>
<h4 id="10-理解BeanPostProcessor实现原理（看源码，有点难）"><a href="#10-理解BeanPostProcessor实现原理（看源码，有点难）" class="headerlink" title="10.理解BeanPostProcessor实现原理（看源码，有点难）"></a>10.理解BeanPostProcessor实现原理（看源码，有点难）</h4><p>在执行postProcessBeforeInitialization方法或postProcessAfterInitialization方法上面添加断点，debug调试测试类。最后找到initializeBean这个方法，点进去查看，会先执行applyBeanPostProcessorsBeforeInitialization这个方法，也就是调用对象初始化方法前执行的方法；然后执行invokeInitMethods方法，就是初始化方法，最后就是执行applyBeanPostProcessorsAfterInitialization方法，即初始化方法执行之后调用的方法。</p>
<ul>
<li>首先执行populateBean方法，给属性设置值。</li>
<li>执行initializeBean方法<ul>
<li>applyBeanPostProcessorsBeforeInitialization</li>
<li>invokeInitMethods</li>
<li>applyBeanPostProcessorsAfterInitialization</li>
</ul>
</li>
</ul>
<h4 id="11-BeanPostProcessor接口在Spring其他类中的使用"><a href="#11-BeanPostProcessor接口在Spring其他类中的使用" class="headerlink" title="11.BeanPostProcessor接口在Spring其他类中的使用"></a>11.BeanPostProcessor接口在Spring其他类中的使用</h4><p>首先咱们来看一下Spring中BeanPostProcessor接口的实现类：</p>
<p><img src="C:\Users\MGL\Desktop\学习笔记\Spring中所有BeanPostProcessor的实现类.jpg" alt="Spring中所有BeanPostProcessor的实现类"></p>
<p>介绍其中的几个：</p>
<ul>
<li>ApplicationContextAwareProcessor：这个可以在我们的<strong>组件</strong>（注入到IOC容器中的的对象）中注入IOC容器。<ul>
<li>具体的注入步骤是：在相应的组件中，实现ApplicationContextAware接口，这个接口有一个方法：public void setApplicationContext(ApplicationContext applicationContext) ，参数就是Spring传入的IOC容器，可以注入到我们的组件中。</li>
<li>注入的时间为：官方文档中写道：注入时间时时在组件的属性赋值完成之后，但是在初始化方法执行之前。参考ApplicationContextAwareProcessor类的源码来看，注入是在postProcessBeforeInitialization这个方法中执行的，也就是之前说的在初始化方法调用前。</li>
</ul>
</li>
<li>BeanValidationPostProcessor：进行数据校验。<ul>
<li>—–在Javabean的初始化方法执行之前之后等，进行校验。</li>
</ul>
</li>
</ul>
<h4 id="12-Value注解和-PropertySource注解给对象的属性赋值"><a href="#12-Value注解和-PropertySource注解给对象的属性赋值" class="headerlink" title="12.@Value注解和@PropertySource注解给对象的属性赋值"></a>12.@Value注解和@PropertySource注解给对象的属性赋值</h4><ul>
<li>@Value注解的使用方法：<ul>
<li>基本的数据类型（int，String，boolean等）</li>
<li>SpEL:用**#{}**的方式，可以计算表达式的值，例如#{20-2}</li>
<li>用${}的方式，可以取出配置文件中的值（key，value）的方式<ul>
<li>在xml中，我们要加载一个配置文件，需要先引入context约束，在配置文件中写 &lt;context:property-placeholder location=”classpath:jdbc.properties” /&gt;类似。</li>
<li>在配置类中，我们我们在类中加上@PropertySource注解，其中的value是一个String类型的数组，可以是多个配置文件。运行时会把这些配置存到环境变量中，可以通过IOC容器获取环境对象Environment，通过这个对象，相应设定的属性就可得到。</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="13-使用-Autowired注解自动注入的讲解"><a href="#13-使用-Autowired注解自动注入的讲解" class="headerlink" title="13.使用@Autowired注解自动注入的讲解"></a>13.使用@Autowired注解自动注入的讲解</h4><ul>
<li>如果不加任何说明，Spring是默认按照<strong>类型</strong>来自动注入的。</li>
<li>如果IOC容器中含有这个类型的多个组件，则将属性的名字作为属性的id来查找。</li>
<li>通过@Qualifie注解来指定装配那个组件，value值为属性id。</li>
<li>通过@Primary注解：让Spring自动装配的时候，默认使用首选的bean。</li>
</ul>
<p>详解@Autowired注解：</p>
<ul>
<li><p>这个注解可以标注在<strong>构造器，方法，方法参数，属性，注解</strong>上。其实都是从IOC容器中获取相应的值。</p>
<ul>
<li><p>关于这个@Autowired注解可以放到类的任意方法中，如下所示。如果这个类中只有一个有参数的构造器，那么可以不写@Autowired这个注解（只可以通过这个构造器实例化对象）。</p>
</li>
<li><p>在@Bean标注的方法创建对象的时候，相应的参数也是从IOC容器中获取的。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Boss</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">     <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> Car car;</span><br><span class="line"></span><br><span class="line">     <span class="meta">@Autowired</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Boss</span><span class="params">( <span class="meta">@Autowired</span> Car car)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.car = car;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Car <span class="title">getCar</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> car;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">     <span class="meta">@Autowired</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setCar</span><span class="params">(Car car)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.car = car;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;Boss&#123;&quot;</span> +</span><br><span class="line">                <span class="string">&quot;car=&quot;</span> + car +</span><br><span class="line">                <span class="string">&#x27;&#125;&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

</li>
</ul>
</li>
</ul>
<h4 id="14-使用-Resource和-Inject注解实现自动注入"><a href="#14-使用-Resource和-Inject注解实现自动注入" class="headerlink" title="14.使用@Resource和@Inject注解实现自动注入"></a>14.使用@Resource和@Inject注解实现自动注入</h4><ul>
<li>@Resource注解：Java 的JSR250规范，可以实现自动注入。<ul>
<li>缺点：默认是按照名称来注入，不支持**@Primary**注解，默认首选注入。</li>
</ul>
</li>
<li>@Inject注解：Java的JSR330规范，可以实现自动注入。<ul>
<li>与@Autowired注解相比，和它实现的功能一致，支持@Primary注解，可以实现默认的首选注入。但是没有、@Autowired的required=false（意思是不必须，可以为null）</li>
</ul>
</li>
</ul>
<p><strong>@Autowired以及@Resource和@Inject注解的工作都是由AutowiredAnnotationBeanPostProcessor这个后置处理器完成工作的。</strong></p>
<h4 id="15-通过Aware接口给自定义的组件添加Spring底层的组件（例如ApplicationContext，Beanfactory等）"><a href="#15-通过Aware接口给自定义的组件添加Spring底层的组件（例如ApplicationContext，Beanfactory等）" class="headerlink" title="15.通过Aware接口给自定义的组件添加Spring底层的组件（例如ApplicationContext，Beanfactory等）"></a>15.通过Aware接口给自定义的组件添加Spring底层的组件（例如ApplicationContext，Beanfactory等）</h4><p>Spring给我们提供了很大的便利，如果我们想在自己定义的组件中添加Spring底层的一些组件，我们只需实现对应的xxxAware接口：例如，我想在我的组件中添加一个ApplicationContext组件，那么我只需要实现ApplicationContextAware接口，Spring在给我们向IOC容器添加组件的时候，就会采用回调的方式，向我们的组件中添加Spring底层的组件。</p>
<p>Spring的Aware接口如下：</p>
<p><img src="C:\Users\MGL\Desktop\Snipaste_2019-06-16_13-51-13.jpg" alt="Snipaste_2019-06-16_13-51-13"></p>
<p>其中选择几个</p>
<ul>
<li>ApplicationContextAware：给我们自定义的组件添加Spring自己的ApplicationContext，即IOC容器。</li>
<li>BeanNameAware：Spring给我们实例化组件后给这个组件起名字。</li>
<li>EmbeddedValueResolverAware：解析字符串，可以解析${}:环境变量的值，#{}spring自定义的。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Blue</span> <span class="keyword">implements</span> <span class="title">ApplicationContextAware</span>, <span class="title">BeanNameAware</span>, <span class="title">EmbeddedValueResolverAware</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> ApplicationContext applicationContext;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setApplicationContext</span><span class="params">(ApplicationContext applicationContext)</span> <span class="keyword">throws</span> BeansException </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.applicationContext = applicationContext;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ApplicationContext <span class="title">getApplicationContext</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> applicationContext;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setBeanName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;bean 的名字是：&quot;</span> + name);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setEmbeddedValueResolver</span><span class="params">(StringValueResolver resolver)</span> </span>&#123;</span><br><span class="line">        String str = <span class="string">&quot;系统名称为：$&#123;os.name&#125;----20*18 = #&#123;20*18&#125;&quot;</span>;</span><br><span class="line">        System.out.println(resolver.resolveStringValue(str));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>处理某个Aware的处理器，就是原来我们说过的PostProcessor：后置处理器，处理ApplicationContextAware的处理器就是ApplicationContextAwarePostProcessor，原理和上面BeanPostProcessor类似。</p>
<h4 id="16-使用-Profile注解实现不同环境的切换"><a href="#16-使用-Profile注解实现不同环境的切换" class="headerlink" title="16.使用@Profile注解实现不同环境的切换"></a>16.使用@Profile注解实现不同环境的切换</h4><p>在开发中可能会遇到这样的问题，假如说开发的时候用到的数据库为数据库a，测试的时候用的是数据库b，而上线的时候用到的事数据库c，那么我们应该如何通过更改更少的代码来实现这个功能呢？</p>
<p>Spring给我们实现了这个功能，我们可以通过给不同的组件添加@Profile注解，在运行的时候激活相应的环境来将对应的组件添加到IOC容器中，比如说，我设置了三个数据库连接池对象，一个添加的@Profile注解为dev，一个为test，一个为prod，那么我在运行的时候如果激活dev环境，那么另外两个组件都不会添加到IOC容器中。</p>
<p>我们来看一下@Profile注解的代码。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Target(&#123;ElementType.TYPE, ElementType.METHOD&#125;)</span></span><br><span class="line"><span class="meta">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class="line"><span class="meta">@Documented</span></span><br><span class="line"><span class="meta">@Conditional(ProfileCondition.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> Profile &#123;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/**</span></span><br><span class="line"><span class="comment">	 * The set of profiles for which the annotated component should be registered.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	String[] value();</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li><p>关于如何激活相应的环境</p>
<ul>
<li>使用命令行参数：-Dspring.profiles.active=你想激活的profile</li>
<li>使用代码激活：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">AnnotationConfigApplicationContext applicationContext = <span class="keyword">new</span> AnnotationConfigApplicationContext();</span><br><span class="line"></span><br><span class="line">applicationContext.getEnvironment().setActiveProfiles(<span class="string">&quot;dev&quot;</span>);</span><br><span class="line"></span><br><span class="line">applicationContext.register(MainConfigOfProfile.class);</span><br><span class="line"></span><br><span class="line">applicationContext.refresh();</span><br></pre></td></tr></table></figure>

</li>
</ul>
<h4 id="17-使用AOP注解开发，通过注解-EnableAspectJAutoProxy注解"><a href="#17-使用AOP注解开发，通过注解-EnableAspectJAutoProxy注解" class="headerlink" title="17.使用AOP注解开发，通过注解@EnableAspectJAutoProxy注解"></a>17.使用AOP注解开发，通过注解@EnableAspectJAutoProxy注解</h4><ul>
<li><p>介绍一些AOP中的名词：</p>
<ul>
<li><code>Aspect</code>（切面）： Aspect 声明类似于 Java 中的类声明，在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。</li>
<li><code>Joint point</code>（连接点）：表示在程序中明确定义的点，典型的包括方法调用，对类成员的访问以及异常处理程序块的执行等等，它自身还可以嵌套其它 joint point。</li>
<li><code>Pointcut</code>（切点）：表示一组 joint point，这些 joint point 或是通过逻辑关系组合起来，或是通过通配、正则表达式等方式集中起来，它定义了相应的 Advice 将要发生的地方。</li>
<li><code>Advice</code>（增强）：Advice 定义了在 <code>Pointcut</code> 里面定义的程序点具体要做的操作，它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。</li>
<li><code>Target</code>（目标对象）：织入 <code>Advice</code> 的目标对象.。</li>
<li><code>Weaving</code>（织入）：将 <code>Aspect</code> 和其他对象连接起来, 并创建 <code>Advice</code>d object 的过程</li>
</ul>
</li>
<li><p>将<strong>切面类</strong>和被<strong>增强的类</strong>添加到IOC容器中，让Spring管理从而实现Spring的切面AOP</p>
</li>
<li><p>被增强的类：</p>
<ul>
<li><pre><code class="java">public class MathCalculate &#123;

    public int div(int x,int y)&#123;
        return x/y;
    &#125;
&#125;

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">- 切面类（XML配置）将相应组件先放入IOC容器中</span><br><span class="line"></span><br><span class="line">  - 在config中配置pointcut：也叫切点。简单来说就是要被增强的方法。</span><br><span class="line"></span><br><span class="line">  - 在config中配置aspect：这里面写的是自己定义的java切面类，定义增强的方法</span><br><span class="line"></span><br><span class="line">  - 在aspect中有五种增强的方法（说四种）：</span><br><span class="line"></span><br><span class="line">    - 在**被增强方法之前**调用的方法：aop:before</span><br><span class="line">    - 在被增强方法之后调用的方法，无论是正常返回还是有异常都会运行：aop:after</span><br><span class="line">    - 在被增强方法正常返回后调用的方法：aop:after-returning</span><br><span class="line">    - 在被增强方法抛出异常后调用的方法：aop:after-throwing</span><br><span class="line"></span><br><span class="line">  - &#96;&#96;&#96;java</span><br><span class="line">    &lt;aop:config&gt;</span><br><span class="line">    		&lt;aop:pointcut id&#x3D;&quot;pointcut1&quot; expression&#x3D;&quot;execution( * cn.jack.aop.MathCalculate.*(..))&quot;&#x2F;&gt;</span><br><span class="line">    		&lt;aop:aspect id&#x3D;&quot;a&quot; ref&#x3D;&quot;aspect&quot;&gt;</span><br><span class="line">    			&lt;aop:before method&#x3D;&quot;logStart&quot; pointcut-ref&#x3D;&quot;pointcut1&quot;&#x2F;&gt;</span><br><span class="line">    			&lt;aop:after method&#x3D;&quot;logEnd&quot; pointcut-ref&#x3D;&quot;pointcut1&quot;&#x2F;&gt;</span><br><span class="line">    			&lt;aop:after-returning method&#x3D;&quot;logReturn&quot; pointcut-ref&#x3D;&quot;pointcut1&quot; returning&#x3D;&quot;arg&quot;&#x2F;&gt;</span><br><span class="line">    			&lt;aop:after-throwing method&#x3D;&quot;logException&quot; throwing&#x3D;&quot;e&quot; pointcut-ref&#x3D;&quot;pointcut1&quot;&#x2F;&gt;</span><br><span class="line">    		&lt;&#x2F;aop:aspect&gt;</span><br><span class="line">    	&lt;&#x2F;aop:config&gt;</span><br><span class="line"></span><br><span class="line">    	&lt;bean id&#x3D;&quot;mathCalculate&quot; class&#x3D;&quot;cn.jack.aop.MathCalculate&quot;&#x2F;&gt;</span><br><span class="line">    	</span><br><span class="line">    	&lt;bean id&#x3D;&quot;aspect&quot; class&#x3D;&quot;cn.jack.aop.AspectJ&quot; &#x2F;&gt;</span><br></pre></td></tr></table></figure>
</code></pre>
</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"></span><br></pre></td></tr></table></figure>
</li>
<li><p>切面类（注解方式）</p>
</li>
<li><p>书写配置类，添加两个注解，@Configration注解和@EnableAspectJAutoProxy注解。</p>
</li>
<li><p>在配置类中将被增强的类和切面类添加到IOC容器中。</p>
<ul>
<li><pre><code class="java">@Aspect
public class LogAspectJ &#123;

    @Pointcut(&quot;execution( public  int cn.jack.aop.MathCalculate.*(..))&quot;)
    public void pointcut()&#123;&#125;

    @Before(&quot;pointcut()&quot;)
    public void logStart(JoinPoint joinPoint)&#123;
        System.out.println(&quot;method  &quot; + joinPoint.getSignature().getName() + &quot;  runs...&quot;);
    &#125;

    @AfterReturning(value = &quot;pointcut()&quot;,returning = &quot;arg&quot;)
    public void logReturn(JoinPoint joinPoint,Object arg)&#123;
        System.out.println(&quot;method&quot; + joinPoint.getSignature().getName() + &quot;  ends, result is  &quot; + arg );
    &#125;

    @After(&quot;pointcut()&quot;)
    public void logEnd(JoinPoint joinPoint)&#123;
        System.out.println(&quot;method &quot; + joinPoint.getSignature().getName() + &quot;  ends&quot;);
    &#125;

    @AfterThrowing(value = &quot;pointcut()&quot;,throwing = &quot;e&quot;)
    public void logException(JoinPoint joinPoint,Exception e)&#123;
        System.out.println(&quot;method &quot; + joinPoint.getSignature().getName() + &quot;  throws exception \n &quot; + e);
    &#125;
&#125;
</code></pre>
</li>
</ul>
</li>
</ul>
<h4 id="18-EnableAspectJAutoProxy注解详解"><a href="#18-EnableAspectJAutoProxy注解详解" class="headerlink" title="18.@EnableAspectJAutoProxy注解详解"></a>18.@EnableAspectJAutoProxy注解详解</h4><ul>
<li><p>这个注解上添加了**@Import(AspectJAutoProxyRegistrar.class)<strong>，而这个@Import注解是向IOC容器中导入一些组件的，所以说，</strong>@EnableAspectJAutoProxy<strong>注解首先是将</strong>AspectJAutoProxyRegistrar**这个类的对象放到IOC容器中。</p>
</li>
<li><p>通过<strong>AspectJAutoProxyRegistrar</strong>这个对象最终给容器注册一个<strong>AnnotationAwareAspectJAutoProxyCreator</strong>对象，定义信息名称为<strong>org.springframework.aop.config.internalAutoProxyCreator</strong>。</p>
</li>
<li><p>AnnotationAwareAspectJAutoProxyCreator对象的继承关系，找寻他的父类</p>
<p>—&gt;AspectJAwareAdvisorAutoProxyCreator</p>
<p>—&gt;AbstractAdvisorAutoProxyCreator</p>
<p>—&gt;AbstractAutoProxyCreator  </p>
<p>​    实现了 <strong>SmartInstantiationAwareBeanPostProcessor</strong>, <strong>BeanFactoryAware</strong> 这两个接口</p>
<ul>
<li><strong>SmartInstantiationAwareBeanPostProcessor</strong> 接口：一个Bean后置处理器，在初始化前后调用相应的方法，详见第11节中所有的BeanPostProcessor继承实现关系或者源代码。</li>
<li><strong>BeanFactoryAware</strong> 接口：自动注入BeanFactory对象。详见15节中Aware的作用。</li>
</ul>
</li>
<li><p>查找接口的方法实现，BeanPostProcessor接口是bean的后置处理器，会有bean初始化之前初始化之后的一些方法，Aware接口是给容器中注册其他容器的接口，会有set方法，查找。</p>
<ul>
<li>AbstractAutoProxyCreator  实现了setBeanFactory方法，postProcessAfterInitialization方法</li>
<li>AbstractAdvisorAutoProxyCreator.setBeanFactory()—-&gt;initBeanFactory()</li>
<li>AspectJAwareAdvisorAutoProxyCreator 无</li>
<li>AnnotationAwareAspectJAutoProxyCreator.initBeanFactory()</li>
</ul>
</li>
<li><p><strong>这个注解工作的总流程：</strong></p>
<ul>
<li>首先获得IOC容器，传入配置类，将IOC容器进行刷新。</li>
<li>registerBeanPostProcessors方法，注册bean的后置处理区来方便对于bean的拦截<ul>
<li>先获取IOC容器中已经定义的需要创建对象的所有BeanPostProcessor</li>
<li>给容器中添加别的BeanPostProcessor</li>
<li>优先注册实现PriorityOrdered接口的BeanPostProcessor</li>
<li>注册实现Ordered接口的BeanPostProcessor</li>
<li>注册常规的BeanPostProcessor</li>
<li>注册BeanPostProcessor就是在IOC容器中添加组件。创建名字为org.springframework.aop.config.internalAutoProxyCreator的BeanPostProcessor–它的类型是【AnnotationAwareAspectJAutoProxyCreator】<ul>
<li>创建bean</li>
<li>populateBean，给bean的各种属性赋值</li>
<li>initializeBean，初始化bean<ul>
<li>invokeAwareMethods，判断是否实例化了Aware接口，调用set方法</li>
<li>applyBeanPostProcessorsBeforeInitialization，后置处理器方法，bean初始化之前调用</li>
<li>invokeInitMethods调用bean的初始化方法</li>
<li>applyBeanPostProcessorsAfterInitialization，后置处理器方法，bean初始化之后调用</li>
</ul>
</li>
<li>BeanPostProcessor创建成功【AnnotationAwareAspectJAutoProxyCreator】</li>
</ul>
</li>
<li>把BeanPostProcessor注册到beanFactory中，beanFactory.addBeanPostProcessor</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>AnnotationAwareAspectJAutoProxyCreator</strong>这个类的工作时机</p>
<ul>
<li>还是先在IOC容器的初始化中的refresh方法中<strong>finishBeanFactoryInitialization</strong>(beanFactory);完成beanfactory的初始化工作，实例所有剩下的bean。<ul>
<li>具体(和之前类似) getBean–&gt;doGetBean–&gt;getSingleton</li>
</ul>
</li>
</ul>
</li>
</ul>

      
    </div>
    <div class="article-footer">
      <blockquote class="mt-2x">
  <ul class="post-copyright list-unstyled">
    
    <li class="post-copyright-link hidden-xs">
      <strong>本文链接：</strong>
      <a href="https://tongxuema.gitee.io/2019/08/12/Spring%20%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%8F%91/" title="Spring 注解开发" target="_blank" rel="external">https://tongxuema.gitee.io/2019/08/12/Spring%20%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%8F%91/</a>
    </li>
    
    <li class="post-copyright-license">
      <strong>版权声明： </strong> 本博客所有文章除特别声明外，均采用 <a href="http://creativecommons.org/licenses/by/4.0/deed.zh" target="_blank" rel="external">CC BY 4.0 CN协议</a> 许可协议。转载请注明出处！
    </li>
  </ul>
</blockquote>


<div class="panel panel-default panel-badger">
  <div class="panel-body">
    <figure class="media">
      <div class="media-left">
        <a href="https://github.com/ysuMgl" target="_blank" class="img-burn thumb-sm visible-lg">
          <img src="https://ftp.bmp.ovh/imgs/2021/03/6eb8924aba7eb620.gif" class="img-rounded w-full" alt="">
        </a>
      </div>
      <div class="media-body">
        <h3 class="media-heading"><a href="https://github.com/ysuMgl" target="_blank"><span class="text-dark">清平愿</span><small class="ml-1x"></small></a></h3>
        <div>长林</div>
      </div>
    </figure>
  </div>
</div>


    </div>
  </article>
  
    
  <section id="comments">
  	
      <div id="vcomments"></div>
    
  </section>


  
</div>

  <nav class="bar bar-footer clearfix" data-stick-bottom>
  <div class="bar-inner">
  
  <ul class="pager pull-left">
    
    <li class="prev">
      <a href="/2021/02/28/hello-world/" title="Hello World"><i class="icon icon-angle-left" aria-hidden="true"></i><span>&nbsp;&nbsp;上一篇</span></a>
    </li>
    
    
    
    <li class="toggle-toc">
      <a class="toggle-btn collapsed" data-toggle="collapse" href="#collapseToc" aria-expanded="false" title="文章目录" role="button">
        <span>[&nbsp;</span><span>文章目录</span>
        <i class="text-collapsed icon icon-anchor"></i>
        <i class="text-in icon icon-close"></i>
        <span>]</span>
      </a>
    </li>
    
  </ul>
  
  
  <!-- Button trigger modal -->
  <button type="button" class="btn btn-fancy btn-donate pop-onhover bg-gradient-warning" data-toggle="modal" data-target="#donateModal"><span>赏</span></button>
  <!-- <div class="wave-icon wave-icon-danger btn-donate" data-toggle="modal" data-target="#donateModal">
    <div class="wave-circle"><span class="icon"><i class="icon icon-bill"></i></span></div>
  </div> -->
  

  <div class="bar-right">
    
    <div class="share-component" data-sites="weibo,qq,wechat,facebook,twitter" data-mobile-sites="weibo,qq,qzone"></div>
    
  </div>
  </div>
</nav>

  
<!-- Modal -->
<div class="modal modal-center modal-small modal-xs-full fade" id="donateModal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content donate">
      <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
      <div class="modal-body">
        <div class="donate-box">
          <div class="donate-head">
            <p>感谢您的支持，我会继续努力的!</p>
          </div>
          <div class="tab-content">
            <div role="tabpanel" class="tab-pane fade active in" id="alipay">
              <div class="donate-payimg">
                <img src="/images/donate/alipayimg.png" alt="扫码支持" title="扫一扫" />
              </div>
              <p class="text-muted mv">扫码打赏，你说多少就多少</p>
              <p class="text-grey">打开支付宝扫一扫，即可进行扫码打赏哦</p>
            </div>
            <div role="tabpanel" class="tab-pane fade" id="wechatpay">
              <div class="donate-payimg">
                <img src="/images/donate/wechatpayimg.png" alt="扫码支持" title="扫一扫" />
              </div>
              <p class="text-muted mv">扫码打赏，你说多少就多少</p>
              <p class="text-grey">打开微信扫一扫，即可进行扫码打赏哦</p>
            </div>
          </div>
          <div class="donate-footer">
            <ul class="nav nav-tabs nav-justified" role="tablist">
              <li role="presentation" class="active">
                <a href="#alipay" id="alipay-tab" role="tab" data-toggle="tab" aria-controls="alipay" aria-expanded="true"><i class="icon icon-alipay"></i> 支付宝</a>
              </li>
              <li role="presentation" class="">
                <a href="#wechatpay" role="tab" id="wechatpay-tab" data-toggle="tab" aria-controls="wechatpay" aria-expanded="false"><i class="icon icon-wepay"></i> 微信支付</a>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>



</main>

  <footer class="footer" itemscope itemtype="http://schema.org/WPFooter">
	
	
    <ul class="social-links">
    	
        <li><a href="https://github.com/ysuMgl" target="_blank" title="Github" data-toggle=tooltip data-placement=top><i class="icon icon-github"></i></a></li>
        
        <li><a href="http://weibo.com/cofess" target="_blank" title="Weibo" data-toggle=tooltip data-placement=top><i class="icon icon-weibo"></i></a></li>
        
        <li><a href="https://gitee.com/tongxuema" target="_blank" title="Gitee" data-toggle=tooltip data-placement=top><i class="icon icon-gitee"></i></a></li>
        
    </ul>

    <div class="copyright">
    	
        <div class="publishby">
        	Theme by <a href="https://github.com/cofess" target="_blank"> cofess </a>base on <a href="https://github.com/cofess/hexo-theme-pure" target="_blank">pure</a>.
        </div>
    </div>
</footer>
  <script src="//cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<script>
window.jQuery || document.write('<script src="js/jquery.min.js"><\/script>')
</script>

<script src="/js/plugin.min.js"></script>


<script src="/js/application.js"></script>


    <script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
            UNTITLED: '(未命名)',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>

<script src="/js/insight.js"></script>






   




   
    
  <script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/valine"></script>
  <script type="text/javascript">
  var GUEST = ['nick', 'mail', 'link'];
  var meta = 'nick,mail,link';
  meta = meta.split(',').filter(function(item) {
    return GUEST.indexOf(item) > -1;
  });
  new Valine({
    el: '#vcomments',
    verify: false,
    notify: false,
    appId: 'h9Tj1iPuyiIpx7pRCM1SrQWO-gzGzoHsz',
    appKey: '5xQxQN6gDAYAjBMKDJzcUVBc',
    placeholder: 'Just go go',
    avatar: 'hide',
    meta: meta,
    pageSize: '10' || 10,
    visitor: true
  });
  </script>

     







</body>
</html>